#ifndef SGU_OBJECT_H
#define SGU_OBJECT_H

SGU_NS_BEGIN

//! Serializable class
/*! Inherit from this class to make a class serializable */
class Serializable
{
	protected:
	//! Default constructor
	Serializable() {}

	//! Default destructor
	virtual ~Serializable() {}

	public:
	//! Serialize to Binary Output Storage
	virtual void serialize(BOStorage &) const = 0;

	//! Serialize from Binary Input Storage
	virtual void serialize(BIStorage &) = 0;
	
	//! Serialize to Text Output Storage
	virtual void serialize(TOStorage &) const = 0;
	
	//! Serialize from Text Input Storage
	virtual void serialize(TIStorage &) = 0;

	//! Get pretty class name
	/*! Should be used to implement text serialization */
	virtual const char * classname() const = 0;
};

#define DECLARE_SERIALIZABLE(T) protected: virtual const char * classname() const {return #T ;}

//! Non copiable class
/*! Inherit from this class to make a class uncopiable */
class NoCopy
{
	public:
	NoCopy() {}
	virtual ~NoCopy() {}
	
	private:
	NoCopy(const NoCopy &);
	void operator = (const NoCopy &);
};




class UsedObj
{
	public:
	UsedObj() {}
	UsedObj(const UsedObj &) {}
	UsedObj & operator = (const UsedObj &) {return *this;}

	virtual ~UsedObj()	
	#ifdef SGU_DEBUG
	{
		ASSERT(_use.empty());
	}
	#else
	{
	}
	#endif

	void addUser(const void* ptr) const
	#ifdef SGU_DEBUG
	{ASSERT(_use.insert(ptr).second);}
	#else
	{}
	#endif

	void delUser(const void* ptr) const
	#ifdef SGU_DEBUG
	{ASSERT(_use.erase(ptr)==1);}
	#else
	{}
	#endif

	
	private:

	#ifdef SGU_DEBUG
	mutable std::set<const void*> _use;
	#endif
};

class UserObj
{
	#ifdef SGU_DEBUG
	public:
	UserObj(void * user, const UsedObj & used) : _user(user), _used(used)
	{
		_used.addUser(_user);
	}

	virtual ~UserObj()
	{
		_used.delUser(_user);
	}

	protected:
	void * _user;
	const UsedObj & _used;
	
	#else
	
	public:
	UserObj(void *, const UsedObj &) {}
	virtual ~UserObj() {}
	#endif
};

/************************************************************/




#define DECLARE_DYNOBJ(T)									\
	public:													\
	static DynObj* s_ctor() {return new T();}				\
	virtual int queryTID() const {return s_tid;}			\
	protected:												\
	virtual ~T() {}											\
	virtual DynObj* clone() const {return new T(*this);}	\
	private:												\
	static const int _s_tid;								\


#define IMPLEMENT_DYNOBJ(T)							\
const int T::_s_tid = TID_##T;						\






/***************************************************/



class DynObj
{
	public:
	typedef DynObj* (*t_sc)();
	virtual int queryTID() const = 0;

	protected:
	DynObj() {}
	DynObj(const DynObj & x) {}

	virtual DynObj * clone() const = 0;


	private:

	void operator = (const DynObj &) {ASSERT(false);}

};


SGU_NS_END

#endif
